package com.xinz.serialization;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;

import com.xinz.protocal.Log;

public class ObjectSerialer extends Serialer {
	
	Class<?> clazz;
	
	Constructor<?> contructor;
	
	Field fields[];
	
	public ObjectSerialer(Class<?> clazz, String[] fields) throws ClassNotFoundException {
		this.clazz = clazz;
		this.fields = new Field[fields.length];
		for (int i = 0; i < fields.length; i++) {
			try {
				this.fields[i] = clazz.getDeclaredField(fields[i]);
				this.fields[i].setAccessible(true);
			}catch (NoSuchFieldException e) {
				Log.warning("缺少字段");
			}
		}
		
		initContructor();
	}
	
	public ObjectSerialer(Class<?> clazz) throws IllegalAccessException{
		this.clazz = clazz;
		Field classFields[] = clazz.getDeclaredFields();
		ArrayList<Field> list = new ArrayList<Field>(classFields.length);
		for(Field field:classFields){
			field.setAccessible(true);
			int modifiers = field.getModifiers();
			//如果是用static 或者transient声明 则不需要传输
			if((modifiers&Modifier.TRANSIENT)!=0
					||(modifiers&Modifier.STATIC)!=0){
				continue;
			}
			list.add(field);
		}
		
		this.fields = list.toArray(new Field[list.size()]);
		initContructor();
	}
	
	void initContructor(){
		try {
			contructor = clazz.getDeclaredConstructor();
			contructor.setAccessible(true);
		} catch (Exception e) {
//			throw new RuntimeException(e.toString());
		}
	}

	@Override
	public Class<?> getType() {
		return clazz;
	}

	@Override
	public void read(Accessor accessor, BeanInputStream in)
			throws Exception {
		Object obj = accessor.get();
		if(obj==null){
			try{
				obj = contructor.newInstance();
				in.addBuff(obj);
			}catch (Exception e) {
				e.printStackTrace();
				throw new Exception(clazz+" 不能初始化");
			}
		}
		int localSize = fields.length;
		FieldAccessor fa = new FieldAccessor();
		for (int i = 0; i < localSize; i++) {
			if(fields[i]!=null){
				fa.setTarget(fields[i],obj);
				in.readAccessor(fa);
			}else{
				in.readAccessor(Accessor.EMPTY);
			}
		}
		accessor.set(obj);
	}

	@Override
	public void write(Accessor accessor, BeanOutputStream out)
			throws Exception {
			Object obj = accessor.get();
			FieldAccessor fa = new FieldAccessor();
			for (int i = 0; i < fields.length; i++) {
				if(fields[i]!=null){
					fa.setTarget(fields[i],obj);
					out.writeAccessor(fa);
				}else{
					out.writeAccessor(null);
				}
			}
	}

}
